﻿
namespace Aeon.Emulator.Instructions.BitShifting
{
    internal static class Sar
    {
        [Opcode("D0/7 rmb", OperandSize = 16 | 32, AddressSize = 16 | 32)]
        public static void ByteArithmeticShiftRight1(Processor p, ref sbyte dest)
        {
            //p.CarryFlag = (dest & 0x01) != 0;
            //p.OverflowFlag = false;
            p.Flags &= ~(EFlags.Carry | EFlags.Overflow);
            p.Flags |= (EFlags)(dest & (int)EFlags.Carry);

            dest >>= 1;
            p.ByteUpdateFlags(dest, (byte)dest, EFlags.Sign | EFlags.Zero | EFlags.Parity);
        }
        [Opcode("D2/7 rmb,cl|C0/7 rmb,ib", OperandSize = 16 | 32, AddressSize = 16 | 32)]
        public static void ByteArithmeticShiftRight(Processor p, ref sbyte dest, byte count)
        {
            count &= 0x1F;
            if(count == 0)
                return;
            else if(count == 1)
            {
                ByteArithmeticShiftRight1(p, ref dest);
                return;
            }

            dest >>= count - 1;
            p.Flags &= ~EFlags.Carry;
            p.Flags |= (EFlags)dest & EFlags.Carry;
            dest >>= 1;
            p.ByteUpdateFlags(dest, (byte)dest, EFlags.Sign | EFlags.Zero | EFlags.Parity);
        }

        [Opcode("D1/7 rmw", AddressSize = 16 | 32)]
        public static void WordArithmeticShiftRight1(Processor p, ref short dest)
        {
            p.Flags &= ~(EFlags.Carry | EFlags.Overflow);
            p.Flags |= (EFlags)(dest & (int)EFlags.Carry);
            dest >>= 1;
            p.WordUpdateFlags(dest, (ushort)dest, EFlags.Sign | EFlags.Zero | EFlags.Parity);
        }
        [Opcode("D3/7 rmw,cl|C1/7 rmw,ib", AddressSize = 16 | 32)]
        public static void WordArithmeticShiftRight(Processor p, ref short dest, byte count)
        {
            count &= 0x1F;
            if(count == 0)
                return;
            else if(count == 1)
            {
                WordArithmeticShiftRight1(p, ref dest);
                return;
            }

            dest >>= count - 1;
            p.Flags &= ~EFlags.Carry;
            p.Flags |= (EFlags)dest & EFlags.Carry;
            dest >>= 1;
            p.WordUpdateFlags(dest, (ushort)dest, EFlags.Sign | EFlags.Zero | EFlags.Parity);
        }

        [Alternate("WordArithmeticShiftRight1", AddressSize = 16 | 32)]
        public static void DWordArithmeticShiftRight1(Processor p, ref int dest)
        {
            p.Flags &= ~(EFlags.Carry | EFlags.Overflow);
            p.Flags |= (EFlags)(dest & (int)EFlags.Carry);
            dest >>= 1;
            p.DWordUpdateFlags(dest, (uint)dest, EFlags.Sign | EFlags.Zero | EFlags.Parity);
        }
        [Alternate("WordArithmeticShiftRight", AddressSize = 16 | 32)]
        public static void DWordArithmeticShiftRight(Processor p, ref int dest, byte count)
        {
            count &= 0x1F;
            if(count == 0)
                return;
            else if(count == 1)
            {
                DWordArithmeticShiftRight1(p, ref dest);
                return;
            }

            dest >>= count - 1;
            p.Flags &= ~EFlags.Carry;
            p.Flags |= (EFlags)dest & EFlags.Carry;
            dest >>= 1;
            p.DWordUpdateFlags(dest, (uint)dest, EFlags.Sign | EFlags.Zero | EFlags.Parity);
        }
    }
}
